/**
 * This file is part of 1genia trampoline
 * Copyright (C) 2007-2008 1genia (contact@1genia.com)
 *
 * This library is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as
 * published by the Free Software Foundation; version 3 of the License. 
 *
 * This library is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Library General Public License for more details. 
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; see the file COPYING.TXT.  If not,
 * write to the Free Software Foundation, Inc., 51 Franklin Street,
 * Fifth Floor, Boston, MA 02110-1301, USA. 
 **/
package com.genia.toolbox.projects.toolbox_basics_project.spring.manager.impl;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

import com.genia.toolbox.basics.bean.Transformer;
import com.genia.toolbox.basics.process.ProxyHelper;
import com.genia.toolbox.projects.toolbox_basics_project.bean.ParameterHandler;
import com.genia.toolbox.projects.toolbox_basics_project.bean.PersistableApplicationParameter;
import com.genia.toolbox.projects.toolbox_basics_project.spring.manager.ParameterHandlerManager;

/**
 * implementation of {@link ParameterHandlerManager}.
 */
public class ParameterHandlerManagerImpl
    implements ParameterHandlerManager
{

  /**
   * {@link Transformer} that allows to retrieve the {@link ParameterHandler}
   * associated to the class of the parameter.
   */
  private final class ClassToParameterHandlerTransformer
      implements Transformer<Class<?>, ParameterHandler<?>>
  {
    /**
     * the transformation method.
     * 
     * @param parameterClass
     *          the class of the parameter
     * @return the {@link ParameterHandler} associated
     */
    public ParameterHandler<?> transform(Class<?> parameterClass)
    {
      ParameterHandler<?> parameterHandler = null;
      LOOP: for (ParameterHandler<?> handler : getHandlers()) {
        if (handler.getHandlingClasses() == null) {
          parameterHandler = handler;
        }
        else {
          for (Class<?> currentClass : handler.getHandlingClasses()) {
            if (currentClass.isAssignableFrom(parameterClass)) {
              parameterHandler = handler;
              break LOOP;
            }
          }
        }
      }
      return parameterHandler;
    }
  }

  /**
   * the map that allow to retrieve the handler of a parameter by the class of
   * the type of its content.
   */
  private transient final Map<Class<?>, ParameterHandler<?>> handlerByParameter = ProxyHelper.getSafeMap(new ConcurrentHashMap<Class<?>, ParameterHandler<?>>(), new ClassToParameterHandlerTransformer());

  /**
   * all the declared {@link PersistableApplicationParameterHandler}.
   */
  private List<ParameterHandler<?>> handlers = new ArrayList<ParameterHandler<?>>();



  /**
   * getter for the handlers property.
   * 
   * @return the handlers
   */
  public List<ParameterHandler<?>> getHandlers()
  {
    return handlers;
  }



  /**
   * setter for the handlers property.
   * 
   * @param handlers
   *          the handlers to set
   */
  public void setHandlers(List<ParameterHandler<?>> handlers)
  {
    this.handlers = handlers;
  }



  /**
   * returns the {@link ParameterHandler} handling the parameter given in
   * parameter.
   * 
   * @param <TYPE>
   *          the type of the parameter to retrieve the handler for
   * @param parameter
   *          the parameter to retrieve the {@link ParameterHandler} for.
   * @return the {@link ParameterHandler} handling the parameter given in
   *         parameter
   * @see com.genia.toolbox.projects.toolbox_basics_project.spring.manager.ParameterHandlerManager#getHandler(com.genia.toolbox.projects.toolbox_basics_project.bean.PersistableApplicationParameter)
   */
  @SuppressWarnings("unchecked")
  public <TYPE> ParameterHandler<TYPE> getHandler(PersistableApplicationParameter<TYPE> parameter)
  {
    return (ParameterHandler<TYPE>) handlerByParameter.get(parameter.getParameterClass());
  }

}
